package org.jeecg.common.util;

import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import java.io.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;


/**
 * 文件工具类
 *
 */
public class FileUtil {


	/**
     * 创建以文本为基础的文件
     * @param savePath		保存文件路劲
     * @param fileName		保存文件名
     * @param encode		文件编码
     * @param content		要保存的文件内容
     * @return
     */
    public static Boolean  createFileByString(String savePath,String fileName,String encode, String content){

    	File dirs = new File(savePath);
    	OutputStreamWriter outputStreamWriter = null;
    	try {
    		if(!dirs.exists()){
        		dirs.mkdirs();
        	}
			OutputStream fileWriter = new FileOutputStream(savePath+File.separator+fileName);
			outputStreamWriter = new OutputStreamWriter(fileWriter, encode);
			outputStreamWriter.write(content);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
            return false;
		}finally {
			try {
				outputStreamWriter.flush();
				outputStreamWriter.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
    }

	/**
     * xml文件创建
     * @param savePath		保存文件路劲
     * @param fileName		保存文件名
     * @param xmlContent	要保存的xml内容
     * @return
     */
    public static Boolean  createXmlFile(String savePath,String fileName, String xmlContent){

    	File dirs = new File(savePath);
    	OutputStreamWriter outputStreamWriter = null;
    	try {
    		if(!dirs.exists()){
        		dirs.mkdirs();
        	}
			OutputStream fileWriter = new FileOutputStream(savePath+File.separator+fileName);
			outputStreamWriter = new OutputStreamWriter(fileWriter, "utf-8");
			outputStreamWriter.write(xmlContent);
			return true;
		} catch (Exception e) {
			e.printStackTrace();
            return false;
		}finally {
			try {
				outputStreamWriter.flush();
				outputStreamWriter.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
    }

    /**
     *
     * 将当前文件夹下是所有文件打包到到当前文件夹下的zipName压缩包里头
     * 或将sourcePath文件打包到自己所在的目录的ipName压缩包里头
     * @param zipName		压缩包名称
     * @param sourcePath	要打包的文件夹或者文件
     * @throws Exception
     */
    public static void createLocalZipFile(String zipName,String sourcePath){

        File sourceFile = new File(sourcePath);
        //创建缓冲输出流
        ZipOutputStream out = null;
        BufferedOutputStream bos = null;
        try {
            System.out.println("压缩中...");
            if(!sourceFile.isDirectory()){
                sourcePath = sourcePath.substring(0, sourcePath.lastIndexOf(File.separator));
            }
            out = new ZipOutputStream(new FileOutputStream(sourcePath+File.separator+zipName));
            bos = new BufferedOutputStream(out);
            compressFileOrDir(out,bos,zipName,sourceFile,"");
            System.out.println("压缩完成...");
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(bos !=null ){
                try {
                    bos.flush();
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 根据输入流创建文件
     * @param savePath      保存目录
     * @param fileName      文件名
     * @param inputStream   文件输入流
     */
    public static void createFileByInputStream(String savePath, String fileName, InputStream inputStream){

        File fileDir  = new File(savePath);
        if(!fileDir.exists()){
            fileDir.mkdirs();
        }
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(savePath + File.separator + fileName);
            int length = 0;
            byte[] buffer = new byte[1204];
            while ((length = inputStream.read(buffer)) != -1) {
                fileOutputStream.write(buffer, 0, length);
            }
        } catch (IOException ex){
            ex.printStackTrace();
        }finally {
            try {
                if(fileOutputStream != null){
                    fileOutputStream.flush();
                    fileOutputStream.close();
                }
                if(inputStream != null){
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 根据字节数组创建文件
     * @param savePath      保存目录
     * @param fileName      文件名
     * @param byteArr   	字节数组
     */
    public static void createFileByByteArr(String savePath, String fileName, byte[] byteArr){

        File fileDir  = new File(savePath);
        if(!fileDir.exists()){
            fileDir.mkdirs();
        }
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(savePath + File.separator + fileName);
            fileOutputStream.write(byteArr);
        } catch (IOException ex){
            ex.printStackTrace();
        }finally {
            try {
                if(fileOutputStream != null){
                    fileOutputStream.flush();
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 读取文件到字节数组
     * @param savePath      文件目录
     * @param fileName      文件名
     */
    public static byte[] readFileToByteArr(String savePath, String fileName){

        File fileDir  = new File(savePath);
        if(!fileDir.exists()){
            fileDir.mkdirs();
        }
        FileInputStream in = null;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
        	in = new FileInputStream(savePath + File.separator + fileName);
            byte[] by = new byte[1024];
            int length = 0;
            while((length = in.read(by))!=-1){
            	out.write(by,0,length);
            }
        } catch (IOException ex){
            ex.printStackTrace();
        }finally {
            try {
                if(out != null){
                	out.flush();
                	out.close();
                }
                if(in != null){
                	in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return out.toByteArray();
    }
    /**
     * 读取文件到字节数组
     * @param inputStream  文件名
     */
    public static byte[] readInputStreamToByteArr(InputStream inputStream){


        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            byte[] by = new byte[1024];
            int length = 0;
            while((length = inputStream.read(by))!=-1){
                out.write(by,0,length);
            }
        } catch (IOException ex){
            ex.printStackTrace();
        }finally {
            try {
                if(out != null){
                    out.flush();
                    out.close();
                }
                if(inputStream != null){
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return out.toByteArray();
    }


    /**
     * 读取文件到字符串
     * @param savePath      文件目录
     * @param encode 		文件编码
     * @param fileName      文件名
     */
    public static String readFileToString(String savePath, String encode,String fileName){

        File fileDir  = new File(savePath);
        if(!fileDir.exists()){
            fileDir.mkdirs();
        }
        FileInputStream in = null;
        BufferedReader br  = null;
        StringBuffer strBuffer = new StringBuffer();
        try {
        	in = new FileInputStream(savePath + File.separator + fileName);
        	br = new BufferedReader(new InputStreamReader(in,encode));
            String lineStr = null;
            while((lineStr = br.readLine())!=null){
            	strBuffer.append(lineStr);
            }
        } catch (IOException ex){
            ex.printStackTrace();
        }finally {
            try {
                if(br != null){
                	br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return strBuffer.toString();
    }

    /**
     * 保存文件到指定目录
     * @param filePath      保存目录
     * @param fileName      文件名
     * @param file          文件
     */
    public static void copyFileToDestFile(String filePath, String fileName, File file){

        File fileDir  = new File(filePath);
        if(!fileDir.exists()){
            fileDir.mkdirs();
        }
        FileOutputStream fileOutputStream = null;
        FileInputStream fileIS  = null;
        try {
            fileOutputStream = new FileOutputStream(filePath + File.separator + fileName);
            fileIS = new FileInputStream(file);
            int length = 0;
            byte[] buffer = new byte[1204];
            while ((length = fileIS.read(buffer)) != -1) {
                fileOutputStream.write(buffer, 0, length);
            }
        } catch (IOException ex){
            ex.printStackTrace();
        }finally {
            try {
                if(fileOutputStream != null){
                    fileOutputStream.flush();
                    fileOutputStream.close();
                }
                if(fileIS != null){
                    fileIS.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
/**
     * 生产zip压缩包
     * @param savePath		打包的位置
     * @param zipName		压缩包名称
     * @param sourcePath	要打包的文件夹或者文件
     * @throws Exception
     */
    public static void createZipFile(String savePath,String zipName,String sourcePath) throws Exception{

        File saveDir = new File(savePath);
        if(!saveDir.exists()){
            saveDir.mkdirs();
        }
        File dirZipFile = new File(sourcePath);
        if(dirZipFile.exists()){
            BufferedOutputStream bos = null;
            try {
                System.out.println("压缩中...");
                ZipOutputStream out = new ZipOutputStream( new FileOutputStream(savePath+File.separator+zipName));

                bos = new BufferedOutputStream(out);
                File sourceFile = new File(sourcePath);

                compressFileOrDir(out,bos,zipName,sourceFile,sourceFile.getName());
                System.out.println("压缩完成");
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                if(bos !=null ){
                    try {
                        bos.flush();
                        bos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    }

	public static void zipFiles(String savepath, String filename,File... srcFiles) throws  Exception {
                // 判断压缩后的文件存在不，不存在则创建
        File dir = new File(savepath);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        File zipFile = new File(savepath+File.separator+filename);

        // 创建 FileOutputStream 对象
        FileOutputStream fileOutputStream = null;
        // 创建 ZipOutputStream
        ZipOutputStream zipOutputStream = null;
        // 创建 FileInputStream 对象
        FileInputStream fileInputStream = null;
        // 实例化 FileOutputStream 对象
             fileOutputStream = new FileOutputStream(zipFile);

            // 实例化 ZipOutputStream 对象
            zipOutputStream = new ZipOutputStream(fileOutputStream);
            // 创建 ZipEntry 对象
            ZipEntry zipEntry = null;
            // 遍历源文件数组
            for (int i = 0; i < srcFiles.length; i++) {
                // 将源文件数组中的当前文件读入 FileInputStream 流中
                fileInputStream = new FileInputStream(srcFiles[i]);
                // 实例化 ZipEntry 对象，源文件数组中的当前文件
                zipEntry = new ZipEntry(srcFiles[i].getName());
                zipOutputStream.putNextEntry(zipEntry);
                // 该变量记录每次真正读的字节个数
                int len;
                // 定义每次读取的字节数组
                byte[] buffer = new byte[1024];
                while ((len = fileInputStream.read(buffer)) > 0) {
                    zipOutputStream.write(buffer, 0, len);
                }
            }
            zipOutputStream.closeEntry();
            zipOutputStream.close();
            fileInputStream.close();

    }

/**
     * 压缩当前文件夹（迭代）
     * @param out			压缩包输出流
     * @param bos			缓存输出流
     * @param zipName   	压缩包名称
     * @param sourceFile	要压缩的文件或文件夹
     * @param base			要压缩的文件或文件夹路径名
     * @throws Exception
     */
    private static void compressFileOrDir(ZipOutputStream out,BufferedOutputStream bos,String zipName, File sourceFile,String base){

        BufferedInputStream bis = null;
        try {
            if(sourceFile.isDirectory()){
                File[] listFiles = sourceFile.listFiles();
                if(listFiles.length>0){																								//如果文件夹里头有文件
                    for(int i=0; i < listFiles.length;i++){
                        if(!listFiles[i].getName().equals(zipName)){
                            compressFileOrDir(out,bos,zipName,listFiles[i],base+File.separator+listFiles[i].getName());				//继续扫描此文件夹下的文件
                        }
                    }
                }else{
                    out.putNextEntry(new ZipEntry(base+"/"));
                }
            }else{
                out.putNextEntry(new ZipEntry(base));
                FileInputStream fos = new FileInputStream(sourceFile);
                bis = new BufferedInputStream(fos);
                int length;
                byte[] by = new byte[1024*1024];
                while((length=bis.read(by))!=-1){					//将源文件写入到zip文件中
                    bos.write(by,0,length);
                }
                bos.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(bis != null){
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 删除当前文件下的所有文件
     * @param fileStr
     */
    public static void deleteSubDir(String fileStr){

        File file = new File(fileStr);
        String[] list = file.list();
        if(list != null && list.length>0){
            for(int i=0;i<list.length;i++){
                File subFile = new File(fileStr + File.separator + list[i]);
                if(subFile.exists()){
                    if(subFile.isDirectory())
                        deleteDir(subFile);
                    else
                        subFile.delete();
                }
            }
        }
    }

    /**
     * 删除文件夹及其所有子文件/文件夹
     * @param dir
     * @return
     */
    public static boolean deleteDir(File dir) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            for (int i=0; i<children.length; i++) {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }
        return dir.delete();
    }


    /**
     * 解压ZIP压缩包
     * @param filePath	ZIP包文件路径
     * @param fileName	ZIP包文件名
     */
    @SuppressWarnings({ "resource", "rawtypes" })
    public  static List<File>   unZip(String filePath,String fileName) {

        InputStream in = null;
        FileOutputStream out = null;
        ZipFile fromZipFile = null;
        List<File> fileList = new ArrayList<>();
        try {
            Charset gbk = Charset.forName("GBK");
            String zipPath = filePath + File.separator + fileName;
            fromZipFile = new ZipFile(zipPath, gbk);
            Enumeration enumer = fromZipFile.entries();
            ZipEntry zipEntry = null;
            while(enumer.hasMoreElements()) {
                zipEntry = (ZipEntry) enumer.nextElement();
                String zipName = zipEntry.getName();
                if(zipEntry.isDirectory()) {
                    zipName = zipName.substring(0, zipName.length() - 1);
                    File unZipChildDir = new File(filePath + File.separator + zipName);
                    if(!unZipChildDir.exists()) {
                        unZipChildDir.mkdirs();
                    }
                } else {
                    File unZipChildFile = new File(filePath + File.separator + zipName);
                    if(!unZipChildFile.getParentFile().exists()) {
                        unZipChildFile.getParentFile().mkdirs();
                    }
                    unZipChildFile.createNewFile();
                    //写文件
                    in = fromZipFile.getInputStream(zipEntry);
                    out = new FileOutputStream(unZipChildFile);
                    byte[] by = new byte[1024];
                    int c;
                    while((c = in.read(by))!=-1){
                        out.write(by,0,c);
                    }
                    fileList.add(unZipChildFile);
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(in != null) {
                try {
                    fromZipFile.close();
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(out != null) {
                try {
                    out.flush();
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return fileList;
    }


    /**
     * 文件下载公用方法
     * @param filePath      文件路径
     * @return
     */
    public static ResponseEntity<byte[]> fileDownload(String filePath) {

        File file = new File(filePath);
        try {
            byte[] fileData = FileUtils.readFileToByteArray(file);
            HttpHeaders headers = new HttpHeaders();

            //headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
            //headers.add("Content-Disposition", "attachment; filename=" + fileName);
            //headers.add("Pragma", "no-cache");

            //headers.add("Expires", "0");
            // headers.add("Last-Modified",  new Date().toString());
            //headers.add("ETag", String.valueOf(System.currentTimeMillis()));

            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentDispositionFormData("attachment", new String(
                    "非居民数据导出.zip".getBytes("UTF-8"), "ISO8859-1"));
            ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(fileData,
                    headers, HttpStatus.CREATED);
            return responseEntity;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

/**
     * 文件下载公用方法
     * @param filePath      文件路径
     * @param fileName      文件名称
     * @return
     */
    public static ResponseEntity<byte[]> fileDownload(String filePath, String fileName) {

        File file = new File(filePath+File.separator+fileName);
        try {
            byte[] fileData = FileUtils.readFileToByteArray(file);
            HttpHeaders headers = new HttpHeaders();

            //headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
            //headers.add("Content-Disposition", "attachment; filename=" + fileName);
            //headers.add("Pragma", "no-cache");

            //headers.add("Expires", "0");
           // headers.add("Last-Modified",  new Date().toString());
            //headers.add("ETag", String.valueOf(System.currentTimeMillis()));

            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentDispositionFormData("attachment", new String(
                    fileName.getBytes("UTF-8"), "ISO8859-1"));
            ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(fileData,
                    headers, HttpStatus.CREATED);
            return responseEntity;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
/**
     * 文件下载公用方法
     * @param inputStream      输入流
     * @param filename      文件名称
     * @return
     */
    public static ResponseEntity<byte[]> fileDownload(String filename,InputStream inputStream) {

        ByteArrayOutputStream bos  = null;
        try {
            bos = new ByteArrayOutputStream();
            HttpHeaders headers = new HttpHeaders();
            byte[] by = new byte[1024];
            int length = 0;
            while((length= inputStream.read(by)) != -1){
                bos.write(by,0,length);
            }
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentDispositionFormData("attachment", new String(
                    filename.getBytes("UTF-8"), "ISO8859-1"));
            ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bos.toByteArray(),
                    headers, HttpStatus.CREATED);
            return responseEntity;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }finally {
            try {
                if(bos != null){

                    bos.flush();
                    bos.close();
                }
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 文件下载公用方法
     * @param bytes      输入流
     * @param filename      文件名称
     * @return
     */
    public static ResponseEntity<byte[]> fileDownload(String filename,byte[] bytes) {
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentDispositionFormData("attachment", new String(
                    filename.getBytes("UTF-8"), "ISO8859-1"));
            ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes,
                    headers, HttpStatus.CREATED);
            return responseEntity;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}
